import { JKManager } from "../JKManager";
import { LocalizedLabel } from "../Language/LocalizedLabel";
import { InfiniteScrollViewCpnt } from "./InfiniteScrollViewCpnt";

const { ccclass, property } = cc._decorator;

export type SearchMode = `Null` | `Music`

let SearchUrls: string[] = [`mp3`]

type UrlObj = {
    url: string,
    fileName: string,
    type: string,
    isFolder: boolean
}

type MusicFile = {
    musicTitle: string,
    musicPath: string,
    musicDurtion: number,
    musicArtist: string
}

/**
 * 选择本地文件组件
 */
@ccclass
export class SelectFilesCpnt extends cc.Component {
    @property(LocalizedLabel)
    labUrl: LocalizedLabel = null
    @property(cc.Node)
    ndBtnReturn: cc.Node = null
    @property(cc.Node)
    ndBtnCancel: cc.Node = null
    @property(cc.Node)
    ndInfiniteScrollViewCpntCtn: cc.Node = null
    @property(cc.Prefab)
    pfbInfiniteScrollViewCpnt: cc.Prefab = null
    @property(cc.Node)
    ndSelectFileItem: cc.Node = null
    @property(cc.Color)
    existedFileColor: cc.Color = null
    @property(cc.Color)
    noExistFileColor: cc.Color = null
    @property(cc.Node)
    ndBtnConfirm: cc.Node = null
    @property(cc.Node)
    ndSfInfiniteSvCpntCtn: cc.Node = null

    private _itemPool: cc.NodePool;
    private _openHistory: { [x: string]: InfiniteScrollViewCpnt; };
    private _folderUrl: string;
    private _labBtnConfirm: LocalizedLabel;
    private _selectedFolderUrlObjs: UrlObj[];
    private _selectCall: (urlObjs: UrlObj[]) => void;
    private _curScInfiniteSvCpnt: InfiniteScrollViewCpnt;
    private _scSfInfiniteSvCpnt: InfiniteScrollViewCpnt;
    private _folderUrlObjs: { [key: string]: UrlObj[] }
    private _searchUrlObjs: UrlObj[];
    private _existedFiles: string[];
    private _maxSelectNum: number;
    private _isShow: boolean;

    onLoad() {
        cc.log(`${cc.js.getClassName(this)} onLoad`)

        this.labUrl.textKey = ``
        this._itemPool = new cc.NodePool()
        this._openHistory = cc.js.createMap()
        this.ndBtnReturn.on(cc.Node.EventType.TOUCH_END, (event: cc.Event.EventTouch) => {
            cc.log(`${cc.js.getClassName(this)} onBtnReturn`)

            if (this.isShow() && cc.sys.isNative && !cc.sys.isBrowser) {
                let keys = this._folderUrl.split(`/`)
                let lastKey = keys.pop()
                lastKey && keys.push(lastKey)
                let len = keys.length
                let targetUrl = ``
                if (len > 0) {
                    if (len === 1) {
                        targetUrl = keys[0] + `/`
                        // if (cc.sys.os === cc.sys.OS_WINDOWS) {
                        //     let rootUrls = `ABCDEFGHIJKLMNOPQRSTUVWXYZ`
                        //     let temp = []
                        //     for (let index = 0; index < rootUrls.length; index++) {
                        //         let rootUrl = `${rootUrls[index]}:/`
                        //         if (jsb.fileUtils.isDirectoryExist(rootUrl)) {
                        //             temp.push(rootUrl)
                        //         }
                        //     }
                        //     temp
                        // }
                    } else {
                        keys.pop()
                        keys.forEach(targetKey => {
                            targetUrl = targetUrl + targetKey + `/`
                        })
                    }
                    this._folderUrl !== targetUrl && this._refresh(targetUrl)
                }
            }
        }, this)
        this.ndBtnCancel.on(cc.Node.EventType.TOUCH_END, (event: cc.Event.EventTouch) => {
            cc.log(`${cc.js.getClassName(this)} onBtnCancel`)

            this.hide()
        }, this)
        this._labBtnConfirm = cc.find(`lab`, this.ndBtnConfirm).getComponent(LocalizedLabel)
        this._selectedFolderUrlObjs = []
        this.ndBtnConfirm.active = false
        this._labBtnConfirm.textKey = JKManager.Language.getText(`queding`)
        this.ndBtnConfirm.on(cc.Node.EventType.TOUCH_END, (event: cc.Event.EventTouch) => {
            cc.log(`${cc.js.getClassName(this)} onBtnConfirm`)

            this._selectCall && this._selectCall(this._selectedFolderUrlObjs)
        }, this)

        // InfiniteScrollViewCpnt
        this.ndSelectFileItem.parent = null
        this._curScInfiniteSvCpnt = cc.instantiate(this.pfbInfiniteScrollViewCpnt).getComponent(this.pfbInfiniteScrollViewCpnt.name)
        this.ndInfiniteScrollViewCpntCtn.addChild(this._curScInfiniteSvCpnt.node)
        this._scSfInfiniteSvCpnt = cc.instantiate(this.pfbInfiniteScrollViewCpnt).getComponent(this.pfbInfiniteScrollViewCpnt.name)
        this.ndSfInfiniteSvCpntCtn.addChild(this._scSfInfiniteSvCpnt.node)
    }

    // ====================================================================================
    // ===================================== 内部接口 ======================================
    // ====================================================================================

    /**
     * 刷新文件列表
     * @param folderUrl 要刷新的目录，默认根目录
     */
    private _refresh(folderUrl: string) {
        cc.log(`${cc.js.getClassName(this)} _refresh folderUrl = ${folderUrl}`)

        this._folderUrl = folderUrl || JKManager.Utils.getRootUrl()
        this.labUrl.textKey = this._folderUrl.replace(/\//g, `\\`)

        let tempUrlObjs = this._folderUrlObjs[this._folderUrl]
        if (!tempUrlObjs) {
            let tempUrls = jsb.fileUtils.listFiles(this._folderUrl),
                urls: string[] = []
            tempUrls.sort()
            tempUrls.forEach(tempUrl => {
                tempUrl = tempUrl.replace(/\\/g, `/`)
                // cc.log(`tempUrl = ${tempUrl}`)
                if (tempUrl[tempUrl.length - 1] === `/`) {
                    if (tempUrl[tempUrl.length - 2] !== `.`) {
                        urls.unshift(tempUrl)
                    }
                } else {
                    urls.push(tempUrl)
                }
            })
            tempUrlObjs = []
            urls.forEach(url => {
                // cc.log(`url = ${url}`)
                if (url) {
                    tempUrlObjs.push(this._localizeUrl(url))
                }
            })
            this._folderUrlObjs[this._folderUrl] = tempUrlObjs
        }

        this._curScInfiniteSvCpnt.node.active = false
        let historyScInfiniteSvCpnt = this._openHistory[this._folderUrl]
        if (historyScInfiniteSvCpnt) {
            this._curScInfiniteSvCpnt = historyScInfiniteSvCpnt
            this._curScInfiniteSvCpnt.node.active = true
        } else {
            this._curScInfiniteSvCpnt = cc.instantiate(this.pfbInfiniteScrollViewCpnt).getComponent(this.pfbInfiniteScrollViewCpnt.name)
            this.ndInfiniteScrollViewCpntCtn.addChild(this._curScInfiniteSvCpnt.node)
            this._curScInfiniteSvCpnt.init(this._folderUrlObjs[this._folderUrl].length, this._createCall.bind(this), this._activeCall.bind(this), false, true)
            this._openHistory[this._folderUrl] = this._curScInfiniteSvCpnt
        }
    }

    /**
     * 本地化文件地址
     * @param url 地址
     */
    private _localizeUrl(url: string) {
        // cc.log(`${cc.js.getClassName(this)} _localizeUrl`)

        let keys = url.split(`/`)
        let isFolder = keys[keys.length - 1] === ``
        let fileName = keys[keys.length - 1] || keys[keys.length - 2] || ``
        keys = fileName.split(`.`)

        return {
            url: url,
            fileName: keys[0] || fileName,
            type: keys[1] && keys[1].toLowerCase() || ``,
            isFolder: isFolder,
        }
    }

    /**
     * 滑动节点创建回调
     * @param index 节点索引
     */
    private _createCall(index: number) {
        // cc.log(`${cc.js.getClassName(this)} _createCall index = ${index}`)

        let item = (this._searchUrlObjs ? this._scSfInfiniteSvCpnt : this._curScInfiniteSvCpnt).getItemFromPoolWithName(this.ndSelectFileItem.name) || cc.instantiate(this.ndSelectFileItem),
            folderUrlObj = this._searchUrlObjs ? this._searchUrlObjs[index] : this._folderUrlObjs[this._folderUrl][index]
        // folderUrlObj = {
        //     url: String,
        //     fileName: String,
        //     type: String,
        //     isFolder: Boolean,
        // }
        let url = folderUrlObj.url,
            fileName = folderUrlObj.fileName,
            type = folderUrlObj.type || ``,
            isFolder = folderUrlObj.isFolder,
            ndSpSelected = cc.find(`content/spSelected`, item),
            selectedIndex = -1,
            lab = cc.find(`content/lab`, item).getComponent(LocalizedLabel),
            ndFolder = cc.find(`content/folder`, item),
            ndFile = cc.find(`content/file`, item),
            existed = this._existedFiles.indexOf(fileName) >= 0 || this._existedFiles.indexOf(url) >= 0
        ndSpSelected.active = false
        for (let index = 0; index < this._selectedFolderUrlObjs.length; index++) {
            let selectedFolderUrlObj = this._selectedFolderUrlObjs[index]
            if (selectedFolderUrlObj === folderUrlObj) {
                ndSpSelected.active = true
                selectedIndex = index

                break
            }
        }
        lab.textKey = `${existed ? `（${JKManager.Language.getText(`yishangchuan`)}）` : ``}${fileName}${type ? `.${type}` : type}`
        lab.node.color = existed ? this.existedFileColor : this.noExistFileColor
        ndFolder.active = isFolder
        ndFile.active = !isFolder

        item.targetOff(this)
        item.on(cc.Node.EventType.TOUCH_END, (event) => {
            cc.log(`${cc.js.getClassName(this)} onBtnFile ${lab.textKey}`)

            if (isFolder) {
                this._refresh(url)
            } else {
                if (!existed) {
                    if (this._selectedFolderUrlObjs.length < this._maxSelectNum || ndSpSelected.active) {
                        ndSpSelected.active = !ndSpSelected.active
                        if (ndSpSelected.active) {
                            this._selectedFolderUrlObjs.push(folderUrlObj)
                        } else {
                            this._selectedFolderUrlObjs.splice(selectedIndex, 1)
                        }
                        this.ndBtnConfirm.active = this._selectedFolderUrlObjs.length > 0
                        this._labBtnConfirm.textKey = this._selectedFolderUrlObjs.length > 0 ? `${JKManager.Language.getText(`queding`)}(${this._selectedFolderUrlObjs.length})` : JKManager.Language.getText(`queding`)
                    } else {
                        // JKManager.Utils.showTip(JKManager.Language.getText(`msgMaxUploadNum`))
                        JKManager.UiManager.showPopupView(`Prefab/Core/CommonDialogView/CommonDialogView`, {
                            msg: JKManager.Language.getText(`msgMaxUploadNum`),
                            callConfirm: () => {
                                cc.log(`${cc.js.getClassName(this)} callConfirm`)

                            }
                        })
                    }
                } else {
                    // JKManager.Utils.showTip(JKManager.Language.getText(`msgExistedFile`))
                    JKManager.UiManager.showPopupView(`Prefab/Core/CommonDialogView/CommonDialogView`, {
                        msg: JKManager.Language.getText(`msgExistedFile`),
                        callConfirm: () => {
                            cc.log(`${cc.js.getClassName(this)} callConfirm`)

                        }
                    })
                }
            }
        }, this)

        return {
            item: item,
            poolName: item.name,
        }
    }

    /**
     * 滑动节点装载或卸载回调
     * @param item 节点
     * @param index 节点索引
     * @param isActive 是否显示状态
     */
    private _activeCall(item: cc.Node, index: number, isActive: boolean) {
        // cc.log(`${cc.js.getClassName(this)} _activeCall index = ${index}`)

        if (isActive) {
            let wdgt = item.getComponent(cc.Widget)
            wdgt.updateAlignment()
        } else {

        }
    }

    /**
     * 搜索文件
     * @param searchMode 搜索模式
     * @param searchTypes 搜索类型
     * @param existedFiles 已存在的文件
     */
    private _searchFile(searchMode: SearchMode, searchTypes: string[], existedFiles: string[]) {
        cc.log(`${cc.js.getClassName(this)} _searchFile searchMode = ${searchMode} searchTypes = `, searchTypes)

        switch (searchMode) {
            case `Music`:
                let searchUrls = SearchUrls
                this._searchUrlObjs = []
                this._existedFiles = []
                searchUrls.forEach(searchUrl => {
                    let tempUrls = jsb.fileUtils.listFiles(searchUrl)
                    tempUrls.sort()
                    tempUrls.forEach(tempUrl => {
                        tempUrl = tempUrl.replace(/\\/g, `/`)
                        let localUrlObj = this._localizeUrl(tempUrl)
                        !localUrlObj.isFolder && searchTypes.indexOf(localUrlObj.type) >= 0 && this._searchUrlObjs.push(localUrlObj)
                    })
                })
                if (this._searchUrlObjs.length > 0) {
                    this._existedFiles = existedFiles
                    this._scSfInfiniteSvCpnt.init(this._searchUrlObjs.length, this._createCall.bind(this), this._activeCall.bind(this), false, true)
                } else {
                    // JKManager.Utils.showTip(JKManager.Language.getText(`msgNoSearchFile`))
                    JKManager.UiManager.showPopupView(`Prefab/Core/CommonDialogView/CommonDialogView`, {
                        msg: JKManager.Language.getText(`msgNoSearchFile`),
                        callConfirm: () => {
                            cc.log(`${cc.js.getClassName(this)} callConfirm`)

                        }
                    })
                }

                break

            default:
                break
        }
    }

    // ====================================================================================
    // ===================================== 外部接口 ======================================
    // ====================================================================================

    /**
     * 显示
     */
    show() {
        // cc.log(`${cc.js.getClassName(this)} show`)

        this._isShow = true
        this.node.active = this._isShow

        return this._isShow
    }

    /**
     * 隐藏
     */
    hide() {
        // cc.log(`${cc.js.getClassName(this)} hide`)

        this._isShow = false
        this.node.active = this._isShow

        return this._isShow
    }

    /**
     * @returns 当前礼物列表显示状态
     */
    isShow() {
        // cc.log(`${cc.js.getClassName(this)} isShow`)

        return this._isShow
    }

    /**
     * 初始化
     * @param selectCall 文件选择回调 (urlObj) urlObj = {url: String, fileName: String, type: String, isFolder: Boolean,}
     * @param folderUrl 要初始化的目录，默认根目录
     * @param maxSelectNum 最大多选文件数
     * @param searchMode 搜索模式
     * @param existedFiles 已存在的文件
     * @param searchMusicFilesCall 外部音乐文件搜索方法(Function (Object musicFiles 音乐文件)) musicFiles = [{ musicTitle : String, musicPath: String, musicDurtion: Number, musicArtist: String,},]
     */
    init(selectCall: (urlObjs: UrlObj[]) => void, folderUrl: string, maxSelectNum = 5, searchMode: SearchMode = `Null`, existedFiles = [], searchMusicFilesCall: (musicFiles: MusicFile[], musicPath: string, musicDurtion: number, musicArtist: string) => void) {
        cc.log(`${cc.js.getClassName(this)} init`)

        if (this.isShow() && cc.sys.isNative && !cc.sys.isBrowser) {
            this._selectCall = selectCall
            this._maxSelectNum = maxSelectNum
            this._selectedFolderUrlObjs = []
            this.ndBtnConfirm.active = false
            this._labBtnConfirm.textKey = JKManager.Language.getText(`queding`)
            switch (searchMode) {
                case `Null`:
                    this.ndBtnReturn.active = true
                    this.ndSfInfiniteSvCpntCtn.active = false
                    this._folderUrlObjs = folderUrl ? cc.js.createMap() : (this._folderUrlObjs || cc.js.createMap())
                    for (const key in this._openHistory) {
                        let historyScInfiniteSvCpnt = this._openHistory[key]
                        historyScInfiniteSvCpnt && historyScInfiniteSvCpnt.destroy()
                    }
                    this._openHistory = cc.js.createMap()
                    this._refresh(folderUrl)

                    break
                case `Music`:
                    this.ndBtnReturn.active = false
                    this.ndSfInfiniteSvCpntCtn.active = true
                    this._searchFile(searchMode, SearchUrls, existedFiles)

                    break

                default:

                    break
            }
        }
    }
}